#include "TestingUtil.h"

bool TestingUtil::TriggerDebugBreakPoint = false;

std::vector<int> TestingUtil::randSizedInts(int size)
{
	std::vector<int> result;
	if (size <= 0)
		return result;
	result.resize(size);
	for (int i = 0; i < size; ++i)
		result[i] = randInt();
	return result;
}

std::vector<int> TestingUtil::randRangeInts(int size, int min_val, int max_val)
{
	std::vector<int> result;
	if (size <= 0)
		return result;
	result.resize(size);
	for (int i = 0; i < size; ++i)
		result[i] = randIntBetween(min_val, max_val);
	return result;
}

std::vector<int> TestingUtil::randOrderedInts(int size, int min_val, int max_val,
                                              std::function<bool(int, int)> cmp_pred)
{
	std::vector<int> nums = randRangeInts(size, min_val, max_val);
	std::sort(nums.begin(), nums.end(), cmp_pred);
	return nums;
}

std::vector<int> TestingUtil::randRangeInts(int size, int min_val, int max_val, float duplicateRate)
{
	std::vector<int> result;
	if (size <= 0)
		return result;
	result.resize(size);

	const int maxDuplicateCount = size * duplicateRate;
	int duplicateCount = 0;

	for (int i = 0; i < size; ++i)
	{
		const bool randDuplicate = i>0 && (duplicateCount < maxDuplicateCount) && (randFloatIn01() <= duplicateRate);
		if(randDuplicate)
		{
			result[i] = result[randIndexInSize(i)];
			duplicateCount++;
		}
		else
		{
			result[i] = randIntBetween(min_val, max_val);
		}
	}
	return result;
}

std::vector<int> TestingUtil::randUniqueRangeInts(int size, int min_val, int max_val)
{
	size = std::min<>(size, max_val - min_val+1);
	if (size <= 0)
		return {};

	std::set<int> result;
	while(result.size()<size)
		result.insert(randIntBetween(min_val, max_val));

	return { result.begin(),result.end() };
}

std::vector<int> TestingUtil::randSizedInts(int min_size, int max_size)
{
	const int rand_size= randIntBetween(min_size, max_size);
	return randSizedInts(rand_size);
}

int TestingUtil::randIndexInSize(std::size_t size)
{
	if (size <= 0)
		return 0;
	return randIntBetween(0, size - 1);
}

int TestingUtil::randIntBetween(int min, int max)
{
	if (min > max)
		std::swap(min, max);
	return min + (max - min) * randFloatIn01();
}
